package com.shop.gc;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

public class OOMError {
    public static void main(String[] args) throws InterruptedException {

        //directBufferError();

        //unable to create new native thread
        //unableCreateNewThreadError();

        //metaSpaceError(args);
    }

    /**
     * GC overhead limit exceeded
     * 超过98%的时间用来做GC并且回收了不到2%的堆内存。
     */
    public static void gcLimit() {
        List<String> list = new ArrayList<>();
        int i = 0 ;
        try {
            while (true){
                list.add(String.valueOf(++i).intern());
            }
        } catch (Exception e) {
            System.out.println("i count ==="+i);
            throw e;
        }
    }

    /**
     * -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
     * Direct buffer memory Error (主要NIO引起)
     */
    public static void directBufferError(){
        System.out.println(sun.misc.VM.maxDirectMemory() / (double) 1024 /1024);
        //分配的为堆外内存
        ByteBuffer.allocateDirect(6 * 1024 * 1024);
    }

    /**
     * unable to create new native thread
     * 这种异常与平台无关
     * 1、这个应用程序创建了多个线程，超载系统极限
     * 2、服务器不允许你的应用程序创建这么多的线程，linux系统默认允许单个进程可以创建的线程是1024个
     */
    public static void unableCreateNewThreadError(){
        Thread thread = new Thread("t1");
        for (int i = 0; ; i++){
            new Thread(()->{
                try{
                    Thread.sleep(Integer.MAX_VALUE);
                }catch (Exception e){

                }
            },i+"").start();
        }
    }

    /**
     * -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxMetaspaceSize=10m
     * java.lang.OutOfMemoryError: Metaspace
     * @param args
     */
    public static void metaSpaceError(String[] args){
        int i = 0 ;
        try{
            while (true){
                i ++;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOMError.class);
                enhancer.setUseCache(false);
                enhancer.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        return methodProxy.invokeSuper(o,args);
                    }
                });
                enhancer.create();
            }
        }catch (Exception e){
            System.out.println("***********次后发生异常"+i);
            e.printStackTrace();
        }
    }

    // java heap space Error
    public static void test() {
        System.out.println("***********HelloGC");
//        Thread.sleep(Integer.MAX_VALUE);
        byte[] a = new byte[50 * 1024 * 1024];
    }
}
